#ifndef _XBENCH_STATE_H
#define _XBENCH_STATE_H

#include <string>
#include <vector>
#include <type_traits>
#include <functional>
#include "xbench/timer.hpp"

namespace xbench{
    class State{
    private:
        std::string _name;
        Timer _timer;
        std::vector<xbench::TimerRecord> _records;
    public:
        State() = default;
        explicit State(const State& state); // 禁用语句: State = const State&
        explicit State(std::string name): _name(std::move(name)){};

        template<class Func>
        void operator|(Func func){
            _timer.restart();
            func();
            _timer.cancel();
            this->_records.emplace_back(_timer);
        }

        template<class Func, class ... Args>
        auto measure(Func func, Args&& ... args) -> decltype(func(args...)){
            _timer.restart();
            if constexpr (std::is_same_v<decltype(func(args...)), void>){
                std::invoke(func, std::forward<Args>(args)...);
                _timer.cancel();
                this->_records.emplace_back(_timer);
            }else{
                auto result = std::invoke(func, std::forward<Args>(args)...);
                _timer.cancel();
                this->_records.emplace_back(_timer);
                return result;
            }
        }

        [[nodiscard]] const std::string& name() const noexcept;
        [[nodiscard]] size_t calls() const noexcept;

        [[nodiscard]] int64_t duration_ns(size_t i) const;
        [[nodiscard]] int64_t duration_ns() const;
    };

    class StateTable{
    private:
        std::vector<const xbench::State*> _states;
    public:
        StateTable() = default;
        void add_state(const xbench::State& state);
        [[nodiscard]] int64_t total_nanoseconds() const;

        [[nodiscard]] const std::vector<const xbench::State*>& get() const;
    };
}

#endif //_XBENCH_STATE_H
